#include "enums.h"
#include "duration.h"
namespace smil
{
    duration::duration() // constructs indefinite
    {
        value = 0;
        state = SYNC_INDEFINITE;
    };
    duration::duration(long int val) // constructs numeric
    {
        value = val;
        state = SYNC_NUMERIC;
    };
    duration::duration(synctype sync) // constructs nonnumeric
    {
        value = 0;
        state = state;
    };

    duration::~duration()
    {
    };
    duration duration::operator= (int that)
    {
        value = that;
        state = SYNC_NUMERIC;
        return *this;
    };
    duration duration::operator= (synctype that)
    {
        value = 0;
        state = that;
        return *this;
    };
    duration duration::operator+ (duration that)
    {
        duration temp;
        if ((state == SYNC_UNRESOLVED) or (that == SYNC_UNRESOLVED)){
            temp = SYNC_UNRESOLVED;
            return temp;}
        if ((state == SYNC_INDEFINITE) or (that == SYNC_INDEFINITE)){
            temp = SYNC_INDEFINITE;
            return temp;}
        temp = value + that.value;
        return temp;
    };
    duration duration::operator- (duration that)
    {
        that.value = that.value * -1;
        duration temp = *this + that;
        return temp;
    };
    duration duration::operator* (float that)
    {
        /*
         *  zero value * value = zero value
         * zero value * indefinite = zero value
         * non-zero value * non-zero value = non-zero value
         * non-zero value * indefinite = indefinite
         * indefinite * indefinite = indefinite
         * unresolved * anything = unresolved
         */
        duration temp;
        if (state == SYNC_UNRESOLVED){
            temp = SYNC_UNRESOLVED;
            return temp;
        }
        if ((that == 0.0) or (value == 0.0)){
            temp = 0;
            return temp;
        }
        if (state == SYNC_INDEFINITE){ // that is nonzero by now
            temp = SYNC_INDEFINITE;
            return temp;
        }
        temp = int ( float (value) * that); // number * number, trimmed to milliseconds
        return temp;
    };

    duration& duration::minimize (duration& that)
    {
        /*
        * MIN( zero value, anything) = zero value
        * MIN( non-zero value, non-zero value) = non-zero value
        * MIN( non-zero value, indefinite) = non-zero value
        * MIN( non-zero value, unresolved) = non-zero value
        * MIN( indefinite, unresolved) = indefinite
        */
        if ((state == SYNC_NUMERIC) and (that == SYNC_NUMERIC)){
            if (value < that.value) return *this;
            else return that;
        }
        if (state == SYNC_NUMERIC) return *this;
        if (that == SYNC_NUMERIC) return that;
        if (state == SYNC_INDEFINITE) return *this;
        return that;
    };
    duration& duration::maximize (duration& that)
    {
        /*
        * MAX( numeric value A, numeric value B) = B if B > A, otherwise A
        * MAX( numeric value, indefinite) = indefinite
        * MAX( numeric value, unresolved) = unresolved
        * MAX( indefinite, unresolved) = unresolved
        */

        if (that == SYNC_UNRESOLVED) return that;
        if (state == SYNC_UNRESOLVED) return *this;
        if (that == SYNC_INDEFINITE) return that;
        if (state == SYNC_INDEFINITE) return *this;
        if (value < that.value) return that;
        return *this;
    };
    duration& minimize(duration& a, duration& b) { return a.minimize(b); }
    duration& maximize(duration& a, duration& b) { return a.maximize(b); }

    bool duration::operator== (duration that)
    {
        if ((value == that.value) and (state == SYNC_NUMERIC) and (that.state == SYNC_NUMERIC)) return true;
        if ((state == that.state) and not(state == SYNC_NUMERIC)) return true; // if they are non-numeric, disregard value;
        return false;
    };

    bool duration::operator== (synctype that)
    {
        if (state == that) return true;
        return false;
    };

    bool duration::operator== (int that)
    {
        if ((state == SYNC_NUMERIC) and (value == that)) return true;
        return false;
    };
}
